package ratiocalc;

public class Ratio {

//  For creating an object that can store a rational number.
//  A rational number can be expressed as a fraction 
//  numerator / denominator

   private int numerator;
   private int denominator;

   public Ratio()
   {
	   this.numerator = 1;
	   this.denominator = 1;
	   
   }
   
   public Ratio(int x)
   {
	   this.numerator = x;
	   this.denominator = 1;
	   
   }
   
   public Ratio (int top, int bottom) throws DivisionByZeroException
   // pre:  bottom != 0
   // post: constructs a ratio equivalent to top / bottom
   {
	   
	  if (bottom != 0)
	  {  
		  numerator = top;
		  denominator = bottom;
		  normalize();
	  }
	  else {
		   throw new DivisionByZeroException ();
	  }
		  
   }
   
   
   public static int gcd(int x, int y)      
       {
               if (y == 0)
                {
               // When x % y is 0, we found the greatest common divisor
   
             return x;
                }
                // Recursion: Algortithm credit:  Euclid & Martin Bilsing 
           return gcd(y, x % y);
   
       }
   
   public static int lcm(int x, int y)
	{
		return Math.abs(x*y)/gcd(x,y);
	}
	
   
   private void normalize ()
   {
	   int gcd = gcd(this.denominator, this.numerator);
	   if (gcd > 1)
	   {
		   this.denominator/=gcd;
		   this.numerator/=gcd;
	   }
	   
   }
   
   public boolean equality (Ratio r) {
	   r.normalize();
	   return (this.numerator==r.getNumerator() 
	   && this.denominator==r.getDenominator());
	   }

   public boolean inequality (Ratio r) {
	   return (!this.equality(r));

   }

   public boolean greaterThan(Ratio r) {
	   int lcm = lcm(this.denominator,r.getDenominator());

	   return (this.numerator * lcm / this.denominator) > 

	   (r.getNumerator() * lcm / r.getDenominator());
   }

   public boolean lessThan(Ratio r) {
	  
	   return (!greaterThan (r));

  }
   
   
   
   public void subFrom(Ratio r)
   {
	   if (!(r.getNumerator()==0))
	   {
		   // if both ratios have the same denominator the numerators are subtracted
		   if (this.denominator == r.getDenominator())
		   {
			   this.numerator -=  r.getNumerator();
		   }
		// if the ratios have different denominators the lowest common denominator 
		   // is determined and the numerators are multiplied accordingly and then subtracted
		   // the denominator of course is the lcm
		   else
		   {
			   // lowest common multiple
			   int lcm = lcm(this.denominator, r.getDenominator());
			   // multiply ratios with factor to get to lcm
			  this.numerator *= lcm/this.denominator;
			  this.numerator -= (r.getNumerator()*(lcm/r.getDenominator()));
			  // denominator is lcm
			  this.denominator = lcm;
			  // normalize
			  normalize();
		   }
	   }
	   
   }
   
   
   
   public void addTo(Ratio r){
       
	   // if ratio to add is zero no action is performed
	   if (!(r.getNumerator() == 0))
	   {
		   // if both ratios have the same denominator the numerators are added
		   if (this.denominator == r.getDenominator())
		   {
			   this.numerator += r.getNumerator();
		   }
		   // if the ratios have different denominators the lowest common denominator 
		   // is determined and the numerators are multiplied accordingly and then added
		   // the denominator of course is the lcm
		   else
		   {
			   // lowest common multiple
			   int lcm = lcm(this.denominator, r.getDenominator());
			   // multiply ratios with factor to get to lcm
			  this.numerator *= lcm/this.denominator;
			  this.numerator += (r.getNumerator()*(lcm/r.getDenominator()));
			  // denominator is lcm
			  this.denominator = lcm;
			  // normalize
			  normalize();
		   }
	   }
      
   }
   
   public void multWith (Ratio r){

	   this.numerator *= r.getNumerator();
	   this.denominator *= r.getDenominator();

	   normalize ();	
	   }

   public void divBy (Ratio r) throws DivisionByZeroException {

	   if (r.getNumerator()!=0) {
	   this.numerator *= r.getDenominator();
	   this.denominator *= r.getNumerator();

	   normalize();
	   }
	   else {
		   throw new DivisionByZeroException (r);
	   }
	
   }
      
   
   public String print () {
	   
	// also write code for printing when 
	// denominator is 1 -> return nominator
	// and for bigger than one fractions, 
	// return 

	String s;
	if (this.numerator==0) {
		return s= "0";
	}
	if (this.denominator == 1) {
	return s= this.numerator+""; // dirty: parse to String lazy
	}

	if (this.numerator>this.denominator) {
	
		if (this.numerator % this.denominator==0){
			return s = this.numerator / this.denominator +"";// dirty again
		}
		else {
	return s = this.numerator / this.denominator + " " + 
	this.numerator % this.denominator + "/" + this.denominator;
	}
	}
	s = this.numerator + "/" + this.denominator;
	return(s);

	}
   
   
   public int getNumerator()
   // post: returns the numerator of the fraction
   {
      return numerator;
   }

   public int getDenominator()
   // post: returns the denominator of the fraction
   {
      return denominator;
   }

   public double value()
   // post: returns the value of the fraction as a real number
   {
      return (double) numerator / (double) denominator;
   }

	
	
	
}
